home *** CD-ROM | disk | FTP | other *** search
- /* advfcn.c - functions for the adventure compiler */
- /*
- Copyright (c) 1986, by David Michael Betz
- All rights reserved
- */
-
- #include "advcom.h"
- #include "advdbs.h"
-
- /* external variables */
- extern char aname[]; /* adventure name */
- extern int aversion; /* adventure version number */
- extern int cptr; /* code space pointer */
- extern int objbuf[]; /* object staging buffer */
- extern int nprops; /* number of properties in current object */
- extern int t_value; /* token value */
- extern char t_token[]; /* token string */
- extern char *t_names[]; /* token names */
- extern int otable[]; /* object table */
- extern int curobj; /* current object number */
- extern int curact; /* current action offset */
- extern int atable[],acnt; /* action table and count */
- extern ARGUMENT *arguments; /* function argument list */
- extern ARGUMENT *temporaries; /* function temporary variable list */
- extern int def_flag; /* default action flag value */
- extern int def_mask; /* default action mask value */
-
- /* external routines */
- extern char *malloc();
- extern char *save();
-
- /* do_adventure - handle the <ADVENTURE name version-number> statement */
- do_adventure()
- {
- /* get the adventure name */
- frequire(T_IDENTIFIER);
- strncpy(aname,t_token,18);
- aname[18] = 0;
-
- /* get the adventure version number */
- frequire(T_NUMBER);
- aversion = t_value;
-
- /* check for the closing paren */
- frequire(T_CLOSE);
- }
-
- /* do_word - enter words of a particular type */
- do_word(type)
- {
- int tkn;
-
- while ((tkn = token()) == T_IDENTIFIER)
- add_word(t_token,type);
- require(tkn,T_CLOSE);
- }
-
- /* do_synonym - handle the <SYNONYMS ... > statement */
- do_synonym()
- {
- int tkn,wrd;
-
- frequire(T_IDENTIFIER);
- wrd = add_word(t_token,WT_UNKNOWN);
- while ((tkn = token()) == T_IDENTIFIER)
- add_synonym(t_token,wrd);
- require(tkn,T_CLOSE);
- }
-
- /* do_define - handle the <DEFINE ... > statement */
- do_define()
- {
- char name[TKNSIZE+1];
- int tkn;
-
- if ((tkn = token()) == T_OPEN)
- return (do_function());
- stoken(tkn);
-
- while ((tkn = token()) == T_IDENTIFIER) {
- strcpy(name,t_token);
- center(name,getvalue());
- }
- require(tkn,T_CLOSE);
- }
-
- /* do_variable - handle the <VARIABLE ... > statement */
- do_variable()
- {
- int tkn;
-
- while ((tkn = token()) == T_IDENTIFIER)
- venter(t_token);
- require(tkn,T_CLOSE);
- }
-
- /* do_defproperty - handle the <PROPERTY ... > statement */
- do_defproperty()
- {
- int tkn;
-
- while ((tkn = token()) == T_IDENTIFIER)
- penter(t_token);
- require(tkn,T_CLOSE);
- }
-
- /* do_default - handle the <DEFAULT ... > statement */
- do_default()
- {
- int tkn;
-
- /* process statements until end of file */
- while ((tkn = token()) == T_OPEN) {
- frequire(T_IDENTIFIER);
- if (match("actor"))
- do_dflag(A_ACTOR);
- else if (match("direct-object"))
- do_dflag(A_DOBJECT);
- else if (match("indirect-object"))
- do_dflag(A_IOBJECT);
- else
- error("Unknown default definition statement type");
- }
- require(tkn,T_CLOSE);
- }
-
- /* do_dflag - handle ACTOR, DIRECT-OBJECT, and INDIRECT-OBJECT statements */
- do_dflag(flag)
- int flag;
- {
- int tkn;
-
- if ((tkn = token()) == T_IDENTIFIER) {
- if (match("required")) {
- def_flag |= flag;
- def_mask &= ~flag;
- }
- else if (match("forbidden")) {
- def_flag &= ~flag;
- def_mask &= ~flag;
- }
- else if (match("optional"))
- def_mask |= flag;
- else
- error("Expecting: REQUIRED, FORBIDDEN or OPTIONAL");
- tkn = token();
- }
- else {
- def_flag |= flag;
- def_mask &= ~flag;
- }
- require(tkn,T_CLOSE);
- }
-
- /* do_object - handle object (LOCATION,OBJECT,ACTOR) definitions */
- int do_object(cname,class)
- char *cname; int class;
- {
- int tkn,obj,obase,osize,i,p;
-
- printf("[ %s: ",cname);
- frequire(T_IDENTIFIER);
- printf("%s ]\n",t_token);
- obj = curobj = oenter(t_token);
-
- /* initialize the object */
- objbuf[O_CLASS/2] = class;
- objbuf[O_NOUNS/2] = NIL;
- objbuf[O_ADJECTIVES/2] = NIL;
- objbuf[O_NPROPERTIES/2] = nprops = 0;
-
- /* copy the property list of the class object */
- if (class) {
- obase = otable[class];
- osize = getword(obase+O_NPROPERTIES);
- for (i = p = 0; i < osize; i++, p += 4)
- if ((getword(obase+O_PROPERTIES+p) & P_CLASS) == 0)
- addprop(getword(obase+O_PROPERTIES+p),0,
- getword(obase+O_PROPERTIES+p+2));
- }
-
- /* process statements until end of file */
- while ((tkn = token()) == T_OPEN) {
- frequire(T_IDENTIFIER);
- if (match("noun"))
- do_noun();
- else if (match("adjective"))
- do_adjective();
- else if (match("property"))
- do_property(0);
- else if (match("class-property"))
- do_property(P_CLASS);
- else if (match("method"))
- do_method();
- else
- error("Unknown object definition statement type");
- }
- require(tkn,T_CLOSE);
-
- /* copy the object to data memory */
- osize = O_SIZE/2 + nprops*2;
- obase = dalloc(osize*2);
- for (i = p = 0; i < osize; i++, p += 2)
- putword(obase+p,objbuf[i]);
- otable[obj] = obase;
- curobj = NIL;
-
- /* return the object number */
- return (obj);
- }
-
- /* do_noun - handle the <NOUN ... > statement */
- do_noun()
- {
- int tkn,new;
-
- while ((tkn = token()) == T_IDENTIFIER) {
- new = dalloc(L_SIZE);
- putword(new+L_DATA,add_word(t_token,WT_NOUN));
- putword(new+L_NEXT,objbuf[O_NOUNS/2]);
- objbuf[O_NOUNS/2] = new;
- }
- require(tkn,T_CLOSE);
- }
-
- /* do_adjective - handle the <ADJECTIVE ... > statement */
- do_adjective()
- {
- int tkn,new;
-
- while ((tkn = token()) == T_IDENTIFIER) {
- new = dalloc(L_SIZE);
- putword(new+L_DATA,add_word(t_token,WT_ADJECTIVE));
- putword(new+L_NEXT,objbuf[O_ADJECTIVES/2]);
- objbuf[O_ADJECTIVES/2] = new;
- }
- require(tkn,T_CLOSE);
- }
-
- /* do_property - handle the <PROPERTY ... > statement */
- do_property(flags)
- int flags;
- {
- int tkn,name,value;
-
- while ((tkn = token()) == T_IDENTIFIER || tkn == T_NUMBER) {
- name = (tkn == T_IDENTIFIER ? penter(t_token) : t_value);
- value = getvalue();
- setprop(name,flags,value);
- }
- require(tkn,T_CLOSE);
- }
-
- /* do_method - handle <METHOD (FUN ...) ... > statement */
- do_method()
- {
- int tkn,name,tcnt;
-
- /* get the property name */
- frequire(T_OPEN);
- frequire(T_IDENTIFIER);
- printf("[ method: %s ]\n",t_token);
-
- /* create a new property */
- name = penter(t_token);
-
- /* allocate a new (anonymous) action */
- if (acnt < AMAX)
- ++acnt;
- else
- error("too many actions");
-
- /* store the action as the value of the property */
- setprop(name,P_CLASS,acnt);
-
- /* initialize the action */
- curact = atable[acnt] = dalloc(A_SIZE);
- putword(curact+A_VERBS,NIL);
- putword(curact+A_PREPOSITIONS,NIL);
- arguments = temporaries = NULL;
- tcnt = 0;
-
- /* enter the "self" argument */
- addargument(&arguments,"self");
- addargument(&arguments,"(dummy)");
-
- /* get the argument list */
- while ((tkn = token()) != T_CLOSE) {
- require(tkn,T_IDENTIFIER);
- if (match("&aux"))
- break;
- addargument(&arguments,t_token);
- }
-
- /* check for temporary variable definitions */
- if (tkn == T_IDENTIFIER)
- while ((tkn = token()) != T_CLOSE) {
- require(tkn,T_IDENTIFIER);
- addargument(&temporaries,t_token);
- tcnt++;
- }
-
- /* store the code address */
- putword(curact+A_CODE,cptr);
-
- /* allocate space for temporaries */
- if (temporaries) {
- putcbyte(OP_TSPACE);
- putcbyte(tcnt);
- }
-
- /* compile the code */
- do_code(NULL);
-
- /* free the argument and temporary variable symbol tables */
- freelist(arguments);
- freelist(temporaries);
- arguments = temporaries = NULL;
- }
-
- /* setprop - set the value of a property */
- setprop(prop,flags,value)
- int prop,flags,value;
- {
- int i;
-
- /* look for the property */
- for (i = 0; i < nprops; i++)
- if ((objbuf[O_PROPERTIES/2 + i*2] & ~P_CLASS) == prop) {
- objbuf[O_PROPERTIES/2 + i*2 + 1] = value;
- return;
- }
- addprop(prop,flags,value);
- }
-
- /* addprop - add a property to the current object's property list */
- addprop(prop,flags,value)
- int prop,flags,value;
- {
- if (nprops >= OPMAX) {
- printf("too many properties for this object\n");
- return;
- }
- objbuf[O_PROPERTIES/2 + nprops*2] = prop|flags;
- objbuf[O_PROPERTIES/2 + nprops*2 + 1] = value;
- objbuf[O_NPROPERTIES/2] = ++nprops;
- }
-
- /* do_code - compile code for an expression */
- int do_code(type)
- char *type;
- {
- int adr,tkn;
-
- if (type) printf("[ compiling %s code ]\n",type);
- adr = putcbyte(OP_PUSH);
- while ((tkn = token()) != T_CLOSE) {
- stoken(tkn);
- do_expr();
- }
- putcbyte(OP_RETURN);
- return (adr);
- }
-
- /* do_action - handle <ACTION ... > statement */
- do_action()
- {
- int tkn,act;
-
- /* get the action name */
- frequire(T_IDENTIFIER);
- printf("[ action: %s ]\n",t_token);
-
- /* create a new action */
- act = aenter(t_token);
- curact = atable[act] = dalloc(A_SIZE);
- putword(curact+A_VERBS,NIL);
- putword(curact+A_PREPOSITIONS,NIL);
- putbyte(curact+A_FLAG,def_flag);
- putbyte(curact+A_MASK,def_mask);
- putword(curact+A_CODE,NIL);
-
- /* process statements until end of file */
- while ((tkn = token()) == T_OPEN) {
- frequire(T_IDENTIFIER);
- if (match("actor"))
- do_flag(A_ACTOR);
- else if (match("verb"))
- do_verb();
- else if (match("direct-object"))
- do_flag(A_DOBJECT);
- else if (match("preposition"))
- do_preposition();
- else if (match("indirect-object"))
- do_flag(A_IOBJECT);
- else if (match("code"))
- putword(curact+A_CODE,do_code(NULL));
- else
- error("Unknown action definition statement type");
- }
- require(tkn,T_CLOSE);
- }
-
- /* do_flag - handle ACTOR, DIRECT-OBJECT, and INDIRECT-OBJECT statements */
- do_flag(flag)
- int flag;
- {
- int tkn;
-
- if ((tkn = token()) == T_IDENTIFIER) {
- if (match("required")) {
- putbyte(curact+A_FLAG,getbyte(curact+A_FLAG) | flag);
- putbyte(curact+A_MASK,getbyte(curact+A_MASK) & ~flag);
- }
- else if (match("forbidden")) {
- putbyte(curact+A_FLAG,getbyte(curact+A_FLAG) & ~flag);
- putbyte(curact+A_MASK,getbyte(curact+A_MASK) & ~flag);
- }
- else if (match("optional"))
- putbyte(curact+A_MASK,getbyte(curact+A_MASK) | flag);
- else
- error("Expecting: REQUIRED, FORBIDDEN or OPTIONAL");
- tkn = token();
- }
- else {
- putbyte(curact+A_FLAG,getbyte(curact+A_FLAG) | flag);
- putbyte(curact+A_MASK,getbyte(curact+A_MASK) & ~flag);
- }
- require(tkn,T_CLOSE);
- }
-
- /* do_verb - handle the <VERB ... > statement */
- do_verb()
- {
- int tkn,new,lst;
-
- while ((tkn = token()) == T_IDENTIFIER || tkn == T_OPEN) {
- new = dalloc(L_SIZE);
- putword(new+L_NEXT,getword(curact+A_VERBS));
- putword(curact+A_VERBS,new);
- lst = dalloc(L_SIZE);
- putword(lst+L_NEXT,NIL);
- putword(new+L_DATA,lst);
- if (tkn == T_IDENTIFIER)
- putword(lst+L_DATA,add_word(t_token,WT_VERB));
- else {
- if ((tkn = token()) == T_IDENTIFIER)
- putword(lst+L_DATA,add_word(t_token,WT_VERB));
- else
- error("Expecting verb");
- while ((tkn = token()) == T_IDENTIFIER) {
- new = dalloc(L_SIZE);
- putword(new+L_DATA,add_word(t_token,WT_UNKNOWN));
- putword(new+L_NEXT,NIL);
- putword(lst+L_NEXT,new);
- lst = new;
- }
- require(tkn,T_CLOSE);
- }
- }
- require(tkn,T_CLOSE);
- }
-
- /* do_preposition - handle the <PREPOSITION ... > statement */
- do_preposition()
- {
- int tkn,new;
-
- while ((tkn = token()) == T_IDENTIFIER) {
- new = dalloc(L_SIZE);
- putword(new+L_DATA,add_word(t_token,WT_PREPOSITION));
- putword(new+L_NEXT,getword(curact+A_PREPOSITIONS));
- putword(curact+A_PREPOSITIONS,new);
- }
- require(tkn,T_CLOSE);
- }
-
- /* do_function - handle <DEFINE (FUN ...) ... > statement */
- do_function()
- {
- int tkn,act,tcnt;
-
- /* get the function name */
- frequire(T_IDENTIFIER);
- printf("[ function: %s ]\n",t_token);
-
- /* create a new action */
- act = aenter(t_token);
-
- /* initialize the action */
- curact = atable[act] = dalloc(A_SIZE);
- putword(curact+A_VERBS,NIL);
- putword(curact+A_PREPOSITIONS,NIL);
- arguments = temporaries = NULL;
- tcnt = 0;
-
- /* get the argument list */
- while ((tkn = token()) != T_CLOSE) {
- require(tkn,T_IDENTIFIER);
- if (match("&aux"))
- break;
- addargument(&arguments,t_token);
- }
-
- /* check for temporary variable definitions */
- if (tkn == T_IDENTIFIER)
- while ((tkn = token()) != T_CLOSE) {
- require(tkn,T_IDENTIFIER);
- addargument(&temporaries,t_token);
- tcnt++;
- }
-
- /* store the code address */
- putword(curact+A_CODE,cptr);
-
- /* allocate space for temporaries */
- if (temporaries) {
- putcbyte(OP_TSPACE);
- putcbyte(tcnt);
- }
-
- /* compile the code */
- do_code(NULL);
-
- /* free the argument and temporary variable symbol tables */
- freelist(arguments);
- freelist(temporaries);
- arguments = temporaries = NULL;
- }
-
- /* addargument - add a formal argument */
- addargument(list,name)
- ARGUMENT **list; char *name;
- {
- ARGUMENT *arg;
-
- if ((arg = (ARGUMENT *)malloc(sizeof(ARGUMENT))) == NULL)
- fail("out of memory");
- arg->arg_name = save(name);
- arg->arg_next = *list;
- *list = arg;
- }
-
- /* freelist - free a list of arguments or temporaries */
- freelist(arg)
- ARGUMENT *arg;
- {
- ARGUMENT *nxt;
-
- while (arg) {
- nxt = arg->arg_next;
- free(arg->arg_name);
- free(arg);
- arg = nxt;
- }
- }
-
- /* findarg - find an argument offset */
- int findarg(name)
- char *name;
- {
- ARGUMENT *arg;
- int n;
-
- for (n = 0, arg = arguments; arg; n++, arg = arg->arg_next)
- if (strcmp(name,arg->arg_name) == 0)
- return (n);
- return (-1);
- }
-
- /* findtmp - find a temporary variable offset */
- int findtmp(name)
- char *name;
- {
- ARGUMENT *tmp;
- int n;
-
- for (n = 0, tmp = temporaries; tmp; n++, tmp = tmp->arg_next)
- if (strcmp(name,tmp->arg_name) == 0)
- return (n);
- return (-1);
- }
-
-